package com.vip.seata.at.order.util;

import com.sun.management.OperatingSystemMXBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.boot.web.context.WebServerApplicationContext;
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
import org.springframework.boot.web.server.WebServer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.lang.annotation.Annotation;
import java.lang.management.ManagementFactory;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author : evan.liu
 * @version V1.0
 * @Description: Application 工具类
 * @date Date : 2022年05月06日 1:28 下午
 */
@Slf4j
@Service
public class ApplicationHelper implements ApplicationContextAware {

	private static ApplicationContext applicationContext;
	public static final int NCPU = Runtime.getRuntime().availableProcessors();
	private static final OperatingSystemMXBean OPERATING_SYSTEM_MX_BEAN = (OperatingSystemMXBean) ManagementFactory
			.getOperatingSystemMXBean();

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		ApplicationHelper.applicationContext = applicationContext;
	}

	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}

	/**
	 * 获取 Application Environment
	 *
	 * @return 环境变量
	 */
	public static Environment getEnvironment() {
		if (ObjectUtils.isEmpty(applicationContext)) {
			return null;
		}
		return applicationContext.getBean(Environment.class);
	}

	/**
	 * 获取应用名称
	 *
	 * @return
	 */
	public static String getApplicationName() {
		if (ObjectUtils.isEmpty(getEnvironment())) {
			return StringPool.EMPTY;
		}
		return getEnvironment().getProperty("spring.application.name");
	}

	/**
	 * 获取应用所在集群
	 *
	 * @return
	 */
	public static String getApplicationCluster() {
		if (ObjectUtils.isEmpty(getEnvironment())) {
			return "default";
		}
		return getEnvironment().getProperty("spring.application.cluster");
	}

	/**
	 * 获取激活的Profile
	 *
	 * @return
	 */
	public static String getProfileActive() {
		if (ObjectUtils.isEmpty(getEnvironment())) {
			return StringPool.EMPTY;
		}
		return getEnvironment().getProperty("spring.profiles.active");
	}




	/**
	 * 获取 AppID
	 *
	 * @param application
	 * @return
	 */
	public static String getApplicationId(String application) {
		return "123456";
	}

	/**
	 * 获取 AppSecret
	 *
	 * @param application
	 * @return
	 */
	public static String getApplicationSecret(String application) {
		return "123456";
	}

	public static float getLoad() {
		return (float) OPERATING_SYSTEM_MX_BEAN.getSystemLoadAverage();
	}

	public static float getCpu() {
		return (float) OPERATING_SYSTEM_MX_BEAN.getSystemCpuLoad();
	}

	public static float getMem() {
		return (float) (1 - (double) OPERATING_SYSTEM_MX_BEAN.getFreePhysicalMemorySize() / (double) OPERATING_SYSTEM_MX_BEAN
				.getTotalPhysicalMemorySize());
	}

	/**
	 * 获取所有的接口实现类
	 *
	 * @param clazz
	 * @return
	 */
	public static <T> Map<String, T> getBeansOfType(Class<T> clazz) {
		Map<String, T> result = applicationContext.getBeansOfType(clazz);
		return result;
	}

	/**
	 * 获取指定的注解类
	 *
	 * @param clazz
	 * @return
	 */
	public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> clazz) {
		Map<String, Object> beansWithAnnotationMap = applicationContext.getBeansWithAnnotation(clazz);
		return beansWithAnnotationMap;
	}

	/**
	 * 根据Class获取Bean
	 *
	 * @param clazz
	 * @return
	 */
	public static <T> T getBean(Class<T> clazz) {
		T result = applicationContext.getBean(clazz);
		return result;
	}

	/**
	 * 根据Name获取Bean
	 *
	 * @param name
	 * @return
	 */
	public static Object getBean(String name) {
		return applicationContext != null ? applicationContext.getBean(name) : null;
	}


	/**
	 * 获取类实现的所有接口
	 *
	 * @param clazz
	 * @return
	 */
	public static Class<? extends Object>[] getInterfaces(Class<? extends Object> clazz) {
		Class<? extends Object>[] interfaces = clazz.getInterfaces();
		return interfaces;
	}

	public static int getCpuCores() {
		int nCpu = Runtime.getRuntime().availableProcessors();
		return nCpu;
	}

	/**
	 * 获取用户目录
	 *
	 * @return user.dir
	 */
	public static String getUserDirectory() {
		return System.getProperty("user.dir");
	}

	/**
	 * 获取临时目录
	 *
	 * @return java.io.tmpdir
	 */
	public static String getTmpDirectory() {
		return System.getProperty("java.io.tmpdir");
	}

	/**
	 * 获取 ClassPath
	 *
	 * @return ClassPath
	 */
	public static String getClassPathDirectory() {
		return ApplicationHelper.class.getClassLoader().getResource("").getPath();
	}

	/**
	 * 获取 ClassPath 指定文件
	 *
	 * @param relativePath 相对路径
	 * @return 文件信息
	 * @throws FileNotFoundException 异常
	 */
	public static File getClassPathFile(String relativePath) throws FileNotFoundException {
		return ResourceUtils.getFile("classpath:" + relativePath);
	}

	/**
	 * 获取 Tomcat 线程池对象
	 *
	 * @param webContext 服务上下文信息
	 * @return 线程池
	 */
	public static ThreadPoolExecutor getTomcatExecutor(WebServerApplicationContext webContext) {
		WebServer webServer = webContext.getWebServer();
		if (webServer instanceof TomcatWebServer) {
			TomcatWebServer server = (TomcatWebServer) webServer;
			return (ThreadPoolExecutor) server.getTomcat().getConnector().getProtocolHandler().getExecutor();
		} else {
			throw new RuntimeException("WebServer not supported:" + WebServer.class.getSimpleName());
		}
	}
}
